#include "serializer/io.h"
#include "serializer/serializer.h"

#include <gtest/gtest.h>

#include <string>
#include <vector>

using namespace serializer;

class CpoTest : public ::testing::Test
{
protected:
    serializer::vector_writer writer_;
    serializer::default_options options_{};
};

/**
 * 测试字符串的序列化和反序列化
 */
TEST_F(CpoTest, StringSerialization)
{
    std::string original = "Hello, CPO World!";
    serialize(writer_, original, options_);

    serializer::vector_reader reader(writer_.data());
    std::string deserialized = serializer::deserialize<std::string>(reader, options_);
    EXPECT_EQ(original, deserialized);

    // 测试空字符串
    writer_.clear();
    std::string empty_original = "";
    serialize(writer_, empty_original, options_);

    serializer::vector_reader reader2(writer_.data());
    std::string empty_deserialized = serializer::deserialize<std::string>(reader2, options_);
    EXPECT_EQ(empty_original, empty_deserialized);
}

/**
 * 测试vector容器的序列化和反序列化
 */
TEST_F(CpoTest, VectorSerialization)
{
    std::vector<int> original = {1, 2, 3, 4, 5};
    serialize(writer_, original, options_);

    serializer::vector_reader reader(writer_.data());
    std::vector<int> deserialized = serializer::deserialize<std::vector<int>>(reader, options_);
    EXPECT_EQ(original, deserialized);

    // 测试空vector
    writer_.clear();
    std::vector<int> empty_original;
    serialize(writer_, empty_original, options_);

    serializer::vector_reader reader2(writer_.data());
    std::vector<int> empty_deserialized =
        serializer::deserialize<std::vector<int>>(reader2, options_);
    EXPECT_EQ(empty_original, empty_deserialized);
}

/**
 * 测试嵌套容器的序列化和反序列化
 */
TEST_F(CpoTest, NestedContainers)
{
    std::vector<std::string> original = {"hello", "world", "test"};
    serialize(writer_, original, options_);

    serializer::vector_reader reader(writer_.data());
    std::vector<std::string> deserialized =
        serializer::deserialize<std::vector<std::string>>(reader, options_);
    EXPECT_EQ(original, deserialized);
}

/**
 * 测试std::pair的序列化和反序列化
 */
TEST_F(CpoTest, PairSerialization)
{
    std::pair<int, std::string> original = {42, "answer"};
    serialize(writer_, original, options_);

    serializer::vector_reader reader(writer_.data());
    auto deserialized = serializer::deserialize<std::pair<int, std::string>>(reader, options_);
    EXPECT_EQ(original.first, deserialized.first);
    EXPECT_EQ(original.second, deserialized.second);
}

/**
 * 测试std::optional的序列化和反序列化
 */
TEST_F(CpoTest, OptionalSerialization)
{
    // 测试有值的optional
    std::optional<int> original_with_value = 42;
    serialize(writer_, original_with_value, options_);

    vector_reader reader(writer_.data());
    auto deserialized_with_value = serializer::deserialize<std::optional<int>>(reader, options_);
    EXPECT_EQ(original_with_value, deserialized_with_value);

    // 测试空的optional
    writer_.clear();
    std::optional<int> original_empty = std::nullopt;
    serialize(writer_, original_empty, options_);

    vector_reader reader2(writer_.data());
    auto deserialized_empty = serializer::deserialize<std::optional<int>>(reader2, options_);
    EXPECT_EQ(original_empty, deserialized_empty);
}

/**
 * 测试字节序转换
 */
TEST_F(CpoTest, ByteOrderConversion)
{
    int original = 0x12345678;

    // 测试小端序
    auto little_endian_options = options_.with_byte_order(serializer::byte_order::little_endian);
    serialize(writer_, original, little_endian_options);

    serializer::vector_reader reader(writer_.data());
    int deserialized = serializer::deserialize<int>(reader, little_endian_options);
    EXPECT_EQ(original, deserialized);

    // 测试大端序
    writer_.clear();
    auto big_endian_options = options_.with_byte_order(serializer::byte_order::big_endian);
    serialize(writer_, original, big_endian_options);

    serializer::vector_reader reader2(writer_.data());
    int deserialized2 = serializer::deserialize<int>(reader2, big_endian_options);
    EXPECT_EQ(original, deserialized2);
}

/**
 * 测试容器大小限制
 */
TEST_F(CpoTest, ContainerSizeLimit)
{
    std::vector<int> large_vector(1000, 42);
    auto limited_options = options_.with_max_container_size(500);

    // 应该抛出异常
    EXPECT_THROW(serialize(writer_, large_vector, limited_options), std::runtime_error);
}

/**
 * 自定义类型的tag_invoke实现测试
 */
struct CustomStruct
{
    int value;
    std::string name;

    bool operator==(const CustomStruct & other) const
    {
        return value == other.value && name == other.name;
    }
};

// 为CustomStruct提供tag_invoke实现
template <typename Writer,
          typename Options,
          typename std::enable_if<serializer::writer<Writer> &&
                                      serializer::serialization_options<Options>,
                                  int>::type = 0>
void
tag_invoke(serializer::serialize_tag_t,
           Writer & writer,
           const CustomStruct & obj,
           const Options & options)
{
    serializer::serialize(writer, obj.value, options);
    serializer::serialize(writer, obj.name, options);
}

template <typename Reader,
          typename Options,
          typename std::enable_if<serializer::reader<Reader> &&
                                      serializer::serialization_options<Options>,
                                  int>::type = 0>
CustomStruct
tag_invoke(serializer::deserialize_tag_t<CustomStruct>, Reader & reader, const Options & options)
{
    CustomStruct result;
    result.value = serializer::deserialize<int>(reader, options);
    result.name = serializer::deserialize<std::string>(reader, options);
    return result;
}

/**
 * 测试自定义类型的tag_invoke实现
 */
TEST_F(CpoTest, CustomTypeTagInvoke)
{
    CustomStruct original{42, "test"};
    serialize(writer_, original, options_);

    vector_reader reader(writer_.data());
    CustomStruct deserialized = serializer::deserialize<CustomStruct>(reader, options_);
    EXPECT_EQ(original, deserialized);
}

/**
 * 测试概念验证
 */
TEST_F(CpoTest, ConceptValidation)
{
    // 验证我们的类型满足概念要求
    static_assert(writer<vector_writer>);
    static_assert(reader<vector_reader>);
    static_assert(serialization_options<default_options>);

    // 验证算术类型概念
    static_assert(arithmetic_type<int>);
    static_assert(arithmetic_type<double>);
    static_assert(!arithmetic_type<std::string>);

    // 验证容器概念
    static_assert(SequenceContainer<std::vector<int>>);
    static_assert(!AssociativeContainer<std::vector<int>>);
}

int
main(int argc, char ** argv)
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}